﻿קונטרולר
==========

`קונטרולר` הינו אובייקט של [CController] או מחלקות היורשות ממנו. הקונטרולר נוצר על ידי האפליקציה כהמשתמש מבקש אותו.
 כשהקונטרולר רץ, הוא מבצע את הפעולה הנחוצה שבדרך כלל נעזרת במודלים ומציגה את התוכן בעזרת קבצי התצוגה.
 `פעולה` (Action), בצורה הכי פשוטה שלו, הינו מתודה במחלקה של הקונטרולר אשר מתחילה ב `action`.

לקונטרולר יש פעולה ברירת מחדל.
 כשמשתמש אשר מבקש את הקונטרולר לא מגדיר איזה פעולה לבצע, פעולה ברירת המחדל היא זו שתרוץ.
 כברירת מחדל, פעולת ברירת המחדל הינה `index`. ניתן לשנות זאת על ידי הגדרת המאפיין [CController::defaultAction].

למטה מוצג הקוד המינימלי כדי ליצור מחלקה לקונטרולר. מאחר ולא קיימים שום פעולות במחלקה במידה והקונטרולר יבוקש על ידי המשתמש תזרק שגיאה.

~~~
[php]
class SiteController extends CController
{
}
~~~

ניתוב
-----

קונטרולרים ופעולות מזוהים על ידי זיהוי יחודי. מזהה יחודי של קונטרולר הוא בפורמט של `path/to/xyz` אשר מכוונת לקובץ המחלקה של הקונטרולר `protected/controllers/path/to/xyzController.php`, כשהמזהה `xyz` יוחלף בשמות אמיתיים של קונטרולרים (לדוגמא `post` מכוון לקובץ `protected/controllers/PostController.php`).
מזהה יחודי של פעולה הינו שמה של המתודה במחלקה ללא הקידומת של `action`. לדוגמא, אם מחלקת הקונטרולר מכילה מתודה בשם `actionEdit`, המזהה היחודי של הפעולה יהיה `edit`.

» Note|הערה: בגרסאות לפני 1.0.3, הפורמט של המזהה היחודי של הקונטרולר היה `path.to.xyz` במקום `path/to/xyz`.

בקשת משתמש עבור קונטרולר ופעולה כלשהי מיוצגת כניתוב.
 נתב נוצר על ידי שרשור של מזהה היחודי של הקונטרולר והמזהה היחודי של הפעולה מופרדים בסלאש (/).
 לדוגמא, הנתב `post/edit` מכוון אל הקונטרולר `PostController` ולפעולה `edit`.
 וכברירת מחדל הקישור `http://hostname/index.php?r=post/edit` יטען את הקונטרולר והפעולה הללו.

» Note|הערה: כברירת מחדל, נתבים רגישים לאותיות גדולות-קטנות.
 מגרסא 1.0.1 ומעלה, ניתן לבטל את הרגישות של הנתבים לאותיות גדולות-קטנות על ידי הגדרת [CUrlManager::caseSensitive] לערך השווה ל `false` בהגדרות של האפליקציה.
 במצב שהנתבים לא רגישים לאותיות גדולות-קטנות, וודא שהינך עוקב אחר המוסכמות ששמות התיקיות המכילות קונטרולרים כתובים באותיות קטנות באנגלית, [מפת קונטרולרים|CWebApplication::controllerMap] ו [מפת פעולות|CController::actions] משתמשים בשמות מפתח באותיות קטנות ובאנגלית.

מגרסא 1.0.3 ומעלה, אפליקציה יכולה להכיל [מודולים](/doc/guide/basics.module). הניתוב לפעולה בקונטרולר שונה בפורמט שלה ועכשיו היא בפורמט של `moduleID/controllerID/actionID`. למידע נוסף קרא אודות [מודולים](/doc/guide/basics.module).

יצירת אובייקט הקונטרולר
------------------------

אובייקט הקונטרולר נוצר כש [CWebApplication] מטפל בבקשה הנכנסת. עם קבלת המזהה היחודי של הקונטרולר, האפליקציה תשתמש בחוקים הבאים כדי להחליט איזה קונטרולר לטעון ואיפה קובץ המחלקה שלו נמצא.

- אם [CWebApplication::catchAllRequest] מוגדר, יווצר קונטרולר בהתבסס על המאפיין הזה, והאפליקציה תתעלם מהקונטרולר שהמשתמש ביקש. מאפיין זה נועד כדי לתפוס את כל בקשות המשתמש ולהכווין אותם אל מקום אחד, לדוגמא במצב של תחזוקה באתר יהיה צורך להציג עמוד אחד שמציג הודעת תחזוקה כלשהי.

- אם המזהה היחודי של הקונטרולר נמצא ב [CWebApplication::controllerMap], ההגדרות של אותו קונטרולר שנמצא ישומשו והאובייקט יווצר בהתבסס על אותם ההגדרות.

- אם המזהה היחודי הוא בפורמט של `path/to/xyz`, שם המחלקה של הקונטרולר יהיה `XyzController` והקובץ ימצא תחת `protected/controllers/path/to/XyzController.php`. לדוגמא, מזהה יחודי של קונטרולר בשם `admin/user` ינותב למחלקה `UserController` וקובץ המחלקה יהיה `protected/controllers/admin/UserController.php` אם קובץ המחלקה לא קיים, תזרק שגיאה 404 [CHttpException].

במקרה של שימוש במודולים (בגרסאות 1.0.3), התהליך המוצג למעלה שונה במקצת. ספציפית, האפליקציה תבדוק אם המזהה היחודי מכוון לקונטרולר בתוך מודול, במידה וכן, אובייקט של המודל יווצר קודם ולאחר מכן יווצר האובייקט של הקונטרולר.

פעולה
------

כפי שצויין, ניתן להגדיר פעולה על ידי יצירת מתודה במחלקה של הקונטרולר כששמה מתחיל ב `action`. דרך יותר מתקדמת תיהיה על ידי יצירת מחלקה לפעולה ולבקש מהקונטרולר ליצור אובייקט שלה כשצריך. דרך זו מאפשרת שימוש חוזר בפעולות ויותר שימושית.

כדי להגדיר פעולה בתור מחלקה יש לבצע את הפעולות הבאות:

~~~
[php]
class UpdateAction extends CAction
{
    public function run()
    {
        // place the action logic here
    }
}
~~~

כדי שהקונטרולר יהיה מודע לפעולה זו, אנחנו דורסים את המתודה [actions|CController::actions] של מחלקת הקונטרולר שלנו:

~~~
[php]
class PostController extends CController
{
    public function actions()
    {
        return array(
            'edit'=»'application.controllers.post.UpdateAction',
        );
    }
}
~~~

בקוד למעלה, אנחנו משתמשים בשם מקוצר `application.controllers.post.UpdateAction` כדי להגדיר שקובץ מחלקת הפעולה נמצא ב `protected/controllers/post/UpdateAction.php`.

באמצעות כתיבת פעולות בתור מחלקות, ניתן לארגן את האפליקציה בצורה מודולרית. לדוגמא, ניתן להשתמש במבנה האפליקציה הבא כדי לארגן את כל הקונטרולרים:

~~~
protected/
    controllers/
        PostController.php
        UserController.php
        post/
            CreateAction.php
            ReadAction.php
            UpdateAction.php
        user/
            CreateAction.php
            ListAction.php
            ProfileAction.php
            UpdateAction.php
~~~

פילטרים
------

פילטר הינו חתיכת קוד אשר מוגדרת לרוץ לפני ו/או אחרי הרצה של פעולה בקונטרולר. לדוגמא, ניתן לבדוק בעזרת פילטר אם משתמש יכול לבצע את הפעולה אותה הוא מנסה להריץ; ניתן להריץ פילטר אשר בודק את משך זמן הרצת הפעולה לצורך קבלת משך זמן הרצת הפעולה.

כל פעולה יכולה להכיל כמה פילטרים. הפילטרים רצים בסדר בהם הם רשומים ברשימת הפילטרים. פילטר יכול למנוע את ההרצה של פעולה כלשהי והרצה של פילטרים נוספים הבאים אחריה.

ניתן להגדיר פילטר בתור מתודה במחלקת הקונטרולר. שם המתודה חייב להתחיל ב `method`. לדוגמא, הקיום של מתודת הפילטר בשם `filterAccessControl` מגדירה פילטר בשם `accessControl`. מתודת הפילטר צריכה להיות חתומה בפורמט של:

~~~
[php]
public function filterAccessControl($filterChain)
{
    // call $filterChain-»run() to continue filtering and action execution
}
~~~

כש `filterChain$` הוא אובייקט של [CFilterChain] אשר מייצג את רשימת הפילטרים המקושרת לפעולה שהתבקשה. בתוך המתודה של הפילטר ניתן לקרוא ל `filterChain-»run$` להמשך הרצת הפילטרים הבאים והרצת הפעולה עצמה.

פילטר יכול להיות גם אובייקט של [CFilter] או מחלקות היורשות ממנו. הקוד הבא מגדיר מחלקת פילטר חדשה:

~~~
[php]
class PerformanceFilter extends CFilter
{
    protected function preFilter($filterChain)
    {
        // logic being applied before the action is executed
        return true; // false if the action should not be executed
    }

    protected function postFilter($filterChain)
    {
        // logic being applied after the action is executed
    }
}
~~~

כדי לצרף פילטרים לפעולות, יש צורך בלדרוס את המתודה `CController::filters`. המתודה צריכה להחזיר מערך עם רשימת הפילטרים וההגדרות שלהם. לדוגמא,

~~~
[php]
class PostController extends CController
{
    ......
    public function filters()
    {
        return array(
            'postOnly + edit, create',
            array(
                'application.filters.PerformanceFilter - edit, create',
                'unit'=»'second',
            ),
        );
    }
}
~~~

הקוד למעלה מגדיר שני פילטרים: `postOnly` ו `PerformanceFilter`. הפילטר `postOnly` הוא פילטר המבוסס על מתודה במחלקה הנוכחית (המתודה של הפילטר כבר מוגדרת ב [CController]); בזמן שהפילטר `PerformanceFilter` הוא מבוסס אובייקט. הנתיב המקוצר `application.filters.PerformanceFilter` מציין שהמחלקה לפילטר נמצאת תחת `protected/filters/PerformanceFilter`. אנחנו משתמשים במערך כדי להגדיר את הפילטר `PerformanceFilter` שיהיה ניתן ליצור אותו בעזרת אותם ערכים כמאפיינים של המחלקה של הפילטר. בדוגמא הזאת המאפיין `unit` יווצר ויוגדר לערך השווה ל `second` במחלקה `PerformanceFilter`.

שימוש באופרטורים של פלוס ומינוס, ניתן להגדיר אילו פעולות הפילטר יצורף אליהם ואילו לא. בדוגמא למעלה, הפילטר `postOnly` יצורף אל הפעולות `edit` ו `create` , בזמן שהפילטר `PerformanceFilter` יצורף אל כל הפעולות **מלבד** `edit` ו `create`. אם בהגדרות הפילטר לא יוגדרו פלוס או מינוס, הפילטר יצורף אל כל הפעולות.

«div class="revision"»$Id: basics.controller.txt 1264 2009-07-21 19:34:55Z qiang.xue $«/div»